home *** CD-ROM | disk | FTP | other *** search
/ Freelog 115 / FreelogNo115-MaiJuin2013.iso / Internet / AvantBrowser / asetup.exe / _data / webkit / resources.pak / Unnamed File 000058.txt < prev    next >
Text File  |  2013-04-03  |  8KB  |  247 lines

  1. // Copyright (c) 2012 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4.  
  5. cr.define('cr.ui', function() {
  6.  
  7.   /** @const */ var Menu = cr.ui.Menu;
  8.  
  9.   /**
  10.    * Handles context menus.
  11.    * @constructor
  12.    */
  13.   function ContextMenuHandler() {}
  14.  
  15.   ContextMenuHandler.prototype = {
  16.  
  17.     /**
  18.      * The menu that we are currently showing.
  19.      * @type {cr.ui.Menu}
  20.      */
  21.     menu_: null,
  22.     get menu() {
  23.       return this.menu_;
  24.     },
  25.  
  26.     /**
  27.      * Shows a menu as a context menu.
  28.      * @param {!Event} e The event triggering the show (usually a contextmenu
  29.      *     event).
  30.      * @param {!cr.ui.Menu} menu The menu to show.
  31.      */
  32.     showMenu: function(e, menu) {
  33.       this.menu_ = menu;
  34.       menu.updateCommands(e.currentTarget);
  35.       menu.hidden = false;
  36.       menu.contextElement = e.currentTarget;
  37.  
  38.       // when the menu is shown we steal all keyboard events.
  39.       var doc = menu.ownerDocument;
  40.       doc.addEventListener('keydown', this, true);
  41.       doc.addEventListener('mousedown', this, true);
  42.       // Note: this should be listening for focus, as in menu_button.js, but
  43.       // as per crbug.com/162190 this indirectly causes odd behaviour.
  44.       // Since the context menu is currently not keyboard-accessible, blur
  45.       // is sufficient for now.
  46.       doc.addEventListener('blur', this, true);
  47.       doc.defaultView.addEventListener('resize', this);
  48.       menu.addEventListener('contextmenu', this);
  49.       menu.addEventListener('activate', this);
  50.       this.positionMenu_(e, menu);
  51.     },
  52.  
  53.     /**
  54.      * Hide the currently shown menu.
  55.      */
  56.     hideMenu: function() {
  57.       var menu = this.menu;
  58.       if (!menu)
  59.         return;
  60.  
  61.       menu.hidden = true;
  62.       menu.contextElement = null;
  63.       var doc = menu.ownerDocument;
  64.       doc.removeEventListener('keydown', this, true);
  65.       doc.removeEventListener('mousedown', this, true);
  66.       doc.removeEventListener('blur', this, true);
  67.       doc.defaultView.removeEventListener('resize', this);
  68.       menu.removeEventListener('contextmenu', this);
  69.       menu.removeEventListener('activate', this);
  70.       menu.selectedIndex = -1;
  71.       this.menu_ = null;
  72.  
  73.       // On windows we might hide the menu in a right mouse button up and if
  74.       // that is the case we wait some short period before we allow the menu
  75.       // to be shown again.
  76.       this.hideTimestamp_ = cr.isWindows ? Date.now() : 0;
  77.     },
  78.  
  79.     /**
  80.      * Positions the menu
  81.      * @param {!Event} e The event object triggering the showing.
  82.      * @param {!cr.ui.Menu} menu The menu to position.
  83.      * @private
  84.      */
  85.     positionMenu_: function(e, menu) {
  86.       // TODO(arv): Handle scrolled documents when needed.
  87.  
  88.       var element = e.currentTarget;
  89.       var x, y;
  90.       // When the user presses the context menu key (on the keyboard) we need
  91.       // to detect this.
  92.       if (this.keyIsDown_) {
  93.         var rect = element.getRectForContextMenu ?
  94.                        element.getRectForContextMenu() :
  95.                        element.getBoundingClientRect();
  96.         var offset = Math.min(rect.width, rect.height) / 2;
  97.         x = rect.left + offset;
  98.         y = rect.top + offset;
  99.       } else {
  100.         x = e.clientX;
  101.         y = e.clientY;
  102.       }
  103.  
  104.       cr.ui.positionPopupAtPoint(x, y, menu);
  105.     },
  106.  
  107.     /**
  108.      * Handles event callbacks.
  109.      * @param {!Event} e The event object.
  110.      */
  111.     handleEvent: function(e) {
  112.       // Keep track of keydown state so that we can use that to determine the
  113.       // reason for the contextmenu event.
  114.       switch (e.type) {
  115.         case 'keydown':
  116.           this.keyIsDown_ = !e.ctrlKey && !e.altKey &&
  117.               // context menu key or Shift-F10
  118.               (e.keyCode == 93 && !e.shiftKey ||
  119.                e.keyIdentifier == 'F10' && e.shiftKey);
  120.           break;
  121.  
  122.         case 'keyup':
  123.           this.keyIsDown_ = false;
  124.           break;
  125.       }
  126.  
  127.       // Context menu is handled even when we have no menu.
  128.       if (e.type != 'contextmenu' && !this.menu)
  129.         return;
  130.  
  131.       switch (e.type) {
  132.         case 'mousedown':
  133.           if (!this.menu.contains(e.target))
  134.             this.hideMenu();
  135.           else
  136.             e.preventDefault();
  137.           break;
  138.         case 'keydown':
  139.           // keyIdentifier does not report 'Esc' correctly
  140.           if (e.keyCode == 27 /* Esc */) {
  141.             this.hideMenu();
  142.             e.stopPropagation();
  143.             e.preventDefault();
  144.  
  145.           // If the menu is visible we let it handle all the keyboard events.
  146.           } else if (this.menu) {
  147.             this.menu.handleKeyDown(e);
  148.             e.preventDefault();
  149.             e.stopPropagation();
  150.           }
  151.           break;
  152.  
  153.         case 'activate':
  154.         case 'blur':
  155.         case 'resize':
  156.           this.hideMenu();
  157.           break;
  158.  
  159.         case 'contextmenu':
  160.           if ((!this.menu || !this.menu.contains(e.target)) &&
  161.               (!this.hideTimestamp_ || Date.now() - this.hideTimestamp_ > 50))
  162.             this.showMenu(e, e.currentTarget.contextMenu);
  163.           e.preventDefault();
  164.           // Don't allow elements further up in the DOM to show their menus.
  165.           e.stopPropagation();
  166.           break;
  167.       }
  168.     },
  169.  
  170.     /**
  171.      * Adds a contextMenu property to an element or element class.
  172.      * @param {!Element|!Function} element The element or class to add the
  173.      *     contextMenu property to.
  174.      */
  175.     addContextMenuProperty: function(element) {
  176.       if (typeof element == 'function')
  177.         element = element.prototype;
  178.  
  179.       element.__defineGetter__('contextMenu', function() {
  180.         return this.contextMenu_;
  181.       });
  182.       element.__defineSetter__('contextMenu', function(menu) {
  183.         var oldContextMenu = this.contextMenu;
  184.  
  185.         if (typeof menu == 'string' && menu[0] == '#') {
  186.           menu = this.ownerDocument.getElementById(menu.slice(1));
  187.           cr.ui.decorate(menu, Menu);
  188.         }
  189.  
  190.         if (menu === oldContextMenu)
  191.           return;
  192.  
  193.         if (oldContextMenu && !menu) {
  194.           this.removeEventListener('contextmenu', contextMenuHandler);
  195.           this.removeEventListener('keydown', contextMenuHandler);
  196.           this.removeEventListener('keyup', contextMenuHandler);
  197.         }
  198.         if (menu && !oldContextMenu) {
  199.           this.addEventListener('contextmenu', contextMenuHandler);
  200.           this.addEventListener('keydown', contextMenuHandler);
  201.           this.addEventListener('keyup', contextMenuHandler);
  202.         }
  203.  
  204.         this.contextMenu_ = menu;
  205.  
  206.         if (menu && menu.id)
  207.           this.setAttribute('contextmenu', '#' + menu.id);
  208.  
  209.         cr.dispatchPropertyChange(this, 'contextMenu', menu, oldContextMenu);
  210.       });
  211.  
  212.       if (!element.getRectForContextMenu) {
  213.         /**
  214.          * @return {!ClientRect} The rect to use for positioning the context
  215.          *     menu when the context menu is not opened using a mouse position.
  216.          */
  217.         element.getRectForContextMenu = function() {
  218.           return this.getBoundingClientRect();
  219.         };
  220.       }
  221.     },
  222.  
  223.     /**
  224.      * Sets the given contextMenu to the given element. A contextMenu property
  225.      * would be added if necessary.
  226.      * @param {!Element} element The element or class to set the contextMenu to.
  227.      * @param {!cr.ui.Menu} contextMenu The contextMenu property to be set.
  228.      */
  229.     setContextMenu: function(element, contextMenu) {
  230.       if (!element.contextMenu)
  231.         this.addContextMenuProperty(element);
  232.       element.contextMenu = contextMenu;
  233.     }
  234.   };
  235.  
  236.   /**
  237.    * The singleton context menu handler.
  238.    * @type {!ContextMenuHandler}
  239.    */
  240.   var contextMenuHandler = new ContextMenuHandler;
  241.  
  242.   // Export
  243.   return {
  244.     contextMenuHandler: contextMenuHandler
  245.   };
  246. });
  247.